package com.zhieasy.interceptors;


import cn.hutool.core.util.ObjectUtil;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.zhieasy.common.annotation.AccessLimit;
import com.zhieasy.common.api.CommonResult;
import com.zhieasy.common.api.ResultCode;
import com.zhieasy.common.util.JsonUtil;

import com.zhieasy.common.util.JwtUtil;
import com.zhieasy.domain.Student;
import com.zhieasy.service.StudentRedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.PrintWriter;

/**
 * 用户操作拦截器
 * @author 风亦未止
 * @date 2021/11/20 21:09
 */
@Slf4j
public class InterceptorDo implements HandlerInterceptor {
    private StudentRedisService studentRedisService;

    public InterceptorDo(StudentRedisService studentRedisService){
        this.studentRedisService=studentRedisService;
    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = null;
//        log.info("拦截器走起~");
        String error = JsonUtil.toJSON(CommonResult.failed(ResultCode.UNAUTHORIZED));
        String token = request.getHeader("token");
        //判断是管理员还是学生
        DecodedJWT verify = null;
        try {
            verify = JwtUtil.verify(token);
        } catch (Exception e) {
            writer=response.getWriter();
            writer.print(error);
            writer.close();
            log.info("token:"+token+" 无效~");
            return false;
        }
        Claim admin = verify.getClaim("admin");
        if ("admin".equals(admin.asString())){
            return true;
        }
        Student student = (Student) studentRedisService.get(token);
        if (ObjectUtil.isNull(student)){
            writer=response.getWriter();
            writer.print(error);
            writer.close();
            log.info("token:"+token+" 无效~");
            return false;
        }
        //拦截登录后过度请求
        if(handler instanceof HandlerMethod){
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            AccessLimit accessLimit = handlerMethod.getMethodAnnotation(AccessLimit.class);
            if (ObjectUtil.isNull(accessLimit)){
                //没有请求方法使用限制访问注解，放行
                return true;
            }
            //每个请求间隔范围（过期时间）
            long seconds = accessLimit.seconds();
            //最大请求数
            int max = accessLimit.maxCount();
            //获取ip地址
            String ip=request.getRemoteAddr();
            String key = request.getServletPath() + ":" + ip ;
            //查询是否有限制缓存：
            Integer count = (Integer) studentRedisService.getLimitTime(key);
            if (ObjectUtil.isNull(count)){
                //无缓存，创建缓存
                studentRedisService.setLimit(key,1,seconds);
                return true;
            }
            if (count<max){
                //小于限定时间范围访问次数
                count=count+1;
                studentRedisService.setLimit(key,count,seconds);
                return true;
            }
            error = JsonUtil.toJSON(CommonResult.failed("操作过于频繁！"));
            writer=response.getWriter();
            writer.print(error);
            writer.close();
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
